"""
时间轴编辑器组件
用于可视化和编辑舞蹈动作序列
"""

import sys
import json
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, 
                             QGraphicsView, QGraphicsScene, QGraphicsItem,
                             QPushButton, QLabel, QFrame, QStyle, QGraphicsTextItem, 
                             QLineEdit, QDialog, QDialogButtonBox, QVBoxLayout as QVLayout,
                             QTextEdit, QMessageBox)
from PyQt5.QtCore import Qt, QRectF, QPointF, pyqtSignal
from PyQt5.QtGui import QPainter, QBrush, QPen, QColor


class ActionEditDialog(QDialog):
    """动作编辑对话框"""
    def __init__(self, action_data, parent=None):
        super().__init__(parent)
        self.action_data = action_data
        self.init_ui()
        
    def init_ui(self):
        self.setWindowTitle("编辑动作")
        self.setModal(True)
        
        layout = QVLayout()
        
        # 动作名称输入
        self.name_edit = QLineEdit(self.action_data.get('name', ''))
        layout.addWidget(QLabel("动作名称:"))
        layout.addWidget(self.name_edit)
        
        # 时间戳输入
        self.timestamp_edit = QLineEdit(str(self.action_data.get('timestamp', 0.0)))
        layout.addWidget(QLabel("时间戳:"))
        layout.addWidget(self.timestamp_edit)
        
        # 持续时间输入
        self.duration_edit = QLineEdit(str(self.action_data.get('duration', 1.0)))
        layout.addWidget(QLabel("持续时间:"))
        layout.addWidget(self.duration_edit)
        
        # 关节角度输入
        self.joint_angles_edit = QTextEdit()
        self.joint_angles_edit.setMaximumHeight(100)
        joint_angles_text = json.dumps(self.action_data.get('joint_angles', {}), indent=2, ensure_ascii=False)
        self.joint_angles_edit.setPlainText(joint_angles_text)
        layout.addWidget(QLabel("关节角度 (JSON格式):"))
        layout.addWidget(self.joint_angles_edit)
        
        # 按钮
        button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
        
        self.setLayout(layout)
        
    def get_action_data(self):
        """获取编辑后的动作数据"""
        try:
            joint_angles = json.loads(self.joint_angles_edit.toPlainText())
        except json.JSONDecodeError:
            joint_angles = self.action_data.get('joint_angles', {})
            
        return {
            'name': self.name_edit.text(),
            'timestamp': float(self.timestamp_edit.text()),
            'duration': float(self.duration_edit.text()),
            'joint_angles': joint_angles
        }


class TimelineActionItem(QGraphicsItem):
    """时间轴上的动作项"""
    
    # 双击信号
    double_clicked = pyqtSignal(object)
    
    def __init__(self, action_data, parent=None):
        super().__init__(parent)
        self.action_data = action_data
        self.width = 80
        self.height = 40
        self.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
        
    def boundingRect(self):
        return QRectF(0, 0, self.width, self.height)
        
    def paint(self, painter, option, widget):
        # 绘制动作项
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 根据选中状态设置颜色
        if option.state & QStyle.State_Selected:
            color = QColor(100, 150, 255)
        else:
            color = QColor(150, 200, 255)
            
        painter.setBrush(QBrush(color))
        painter.setPen(QPen(Qt.black, 1))
        painter.drawRoundedRect(0, 0, self.width, self.height, 5, 5)
        
        # 绘制文本
        painter.setPen(Qt.black)
        painter.drawText(self.boundingRect(), Qt.AlignCenter, 
                        self.action_data.get('name', '动作'))
    
    def mouseDoubleClickEvent(self, event):
        """处理双击事件"""
        # 弹出编辑对话框
        dialog = ActionEditDialog(self.action_data)
        if dialog.exec_() == QDialog.Accepted:
            # 更新动作数据
            self.action_data.update(dialog.get_action_data())
            # 重新绘制
            self.update()
        super().mouseDoubleClickEvent(event)


class TimelineEditorWidget(QWidget):
    """时间轴编辑器主控件"""
    
    # 动作数据变化信号
    actions_changed = pyqtSignal()
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.init_ui()
        self.actions = []
        
    def init_ui(self):
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        
        # 控制按钮
        control_layout = QHBoxLayout()
        self.add_btn = QPushButton("添加动作")
        self.delete_btn = QPushButton("删除动作")
        self.add_btn.clicked.connect(self.add_action)
        self.delete_btn.clicked.connect(self.delete_action)
        control_layout.addWidget(self.add_btn)
        control_layout.addWidget(self.delete_btn)
        control_layout.addStretch()
        
        # 时间轴视图
        self.view = QGraphicsView()
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)
        self.view.setRenderHint(QPainter.Antialiasing)
        
        # 设置时间轴背景
        self.scene.setSceneRect(0, 0, 800, 100)
        
        layout.addLayout(control_layout)
        layout.addWidget(self.view)
        
    def add_action(self):
        """添加新动作"""
        action_data = {
            'name': f'动作{len(self.actions)+1}',
            'timestamp': len(self.actions) * 1.0,
            'duration': 1.0,
            'joint_angles': {
                'left_arm': 0,
                'right_arm': 0,
                'left_leg': 0,
                'right_leg': 0,
                'head': 0
            }
        }
        
        action_item = TimelineActionItem(action_data)
        action_item.setPos(len(self.actions) * 100, 30)
        self.scene.addItem(action_item)
        self.actions.append(action_item)
        
        # 发出动作变化信号
        self.actions_changed.emit()
        
    def add_preset_action(self, preset_action_data):
        """添加预设动作"""
        action_data = {
            'name': preset_action_data.get('name', f'动作{len(self.actions)+1}'),
            'timestamp': len(self.actions) * 1.0,
            'duration': preset_action_data.get('duration', 1.0),
            'joint_angles': preset_action_data.get('joint_angles', {
                'left_arm': 0,
                'right_arm': 0,
                'left_leg': 0,
                'right_leg': 0,
                'head': 0
            })
        }
        
        action_item = TimelineActionItem(action_data)
        action_item.setPos(len(self.actions) * 100, 30)
        self.scene.addItem(action_item)
        self.actions.append(action_item)
        
        # 发出动作变化信号
        self.actions_changed.emit()
        
    def delete_action(self):
        """删除选中的动作"""
        selected_items = self.scene.selectedItems()
        for item in selected_items:
            self.scene.removeItem(item)
            if item in self.actions:
                self.actions.remove(item)
        
        # 发出动作变化信号
        self.actions_changed.emit()
        
    def get_actions_data(self):
        """获取所有动作数据"""
        return [item.action_data for item in self.actions]
        
    def set_actions_data(self, actions_data):
        """设置动作数据"""
        # 清除现有动作
        for item in self.actions:
            self.scene.removeItem(item)
        self.actions.clear()
        
        # 添加新动作
        for i, action_data in enumerate(actions_data):
            action_item = TimelineActionItem(action_data)
            action_item.setPos(i * 100, 30)
            self.scene.addItem(action_item)
            self.actions.append(action_item)
            
        # 发出动作变化信号
        self.actions_changed.emit()
        
    def update_from_json(self, json_text):
        """从JSON文本更新动作数据"""
        try:
            actions_data = json.loads(json_text)
            if isinstance(actions_data, list):
                self.set_actions_data(actions_data)
                return True
            else:
                QMessageBox.warning(self, "错误", "JSON格式不正确，应该是一个动作数组")
                return False
        except json.JSONDecodeError as e:
            QMessageBox.warning(self, "错误", f"JSON解析失败: {str(e)}")
            return False
            
    def get_sequence_data(self):
        """获取序列数据，用于保存序列"""
        return self.get_actions_data()
        
    def set_sequence_data(self, sequence_data):
        """设置序列数据，用于加载序列"""
        if isinstance(sequence_data, list):
            self.set_actions_data(sequence_data)
            
    def clear_sequence(self):
        """清空序列数据"""
        # 清除现有动作
        for item in self.actions:
            self.scene.removeItem(item)
        self.actions.clear()
        
        # 发出动作变化信号
        self.actions_changed.emit()